///定义一个Dart类，所有的类都继承自Object
class Person {
  String name;
  int age;

  Person(this.name, this.age);

  ///充血父类方法
  @override
  String toString() {
    // TODO: implement toString
    return super.toString();
  }
}

class Student extends Person {
  //定义类的变量
  String _school; //通过下划线来标示私有字段（变量）
  String city;
  String country;
  String name;

  //可以为私有字段设置getter来让外界获取到私有字段
  String get school => _school;
  //可以为私有字段设置setter来控制外界对私有字段的修改
  set school(String value){
    _school = value;
  }

  //静态方法
  static doPrint(String mess){
    print(mess);
  }

  ///构造方法：
  ///通过this._school初始化自由参数
  ///name,age交给父类进行初始化
  ///city为可选参数
  ///country为默认参数
  Student(this._school, String name, int age,
      {this.city, this.country = "China"})
      :
        ///初始化列表，除了调用父类构造器，在子类构造器方法体之前
        ///你也可以初始化实例变量，不同的初始化变量之间用逗号隔开
        name = '$country.$country',

        ///如果父类没有默认构造方法（无参的构造方法）
        ///则需要在初始化列表汇中调用父类的构造方法进行初始化
        super(name, age) {
    ///构造方法体不是必须的
    print("构造方法体不是必须的");
  }

  ///命名构造方法[类名+.+方法名]
  ///使用命名构造方法为类实现多个构造方法
  Student.get(Student stu) : super(stu.name, stu.age) {
    print("命名构造方法");
  }

  ///命名工厂构造方法： factory [类名+.+方法名]
  ///它可以有返回值，而且不需要将类的final变量作为参数，是提供一种灵活获取类对象的方法
  factory Student.stu(Student stu){
    return Student(stu._school,stu.name,stu.age);
  }
}

class Logger {
  static Logger _cache;
  /// 工厂构造方法：
  /// 不仅仅是构造方法，更是一种模式
  /// 有时候为了返回一个之前已经创建的缓存对象，原始的构造方法已经不能满足要求
  /// 那么可以使用工厂模式来定义构造方法
  factory Logger() {
    if(_cache == null){
      _cache = Logger._internal();
    }
    return _cache;
  }
  Logger._internal();

  void log(String mess){
    print(mess);
  }
}

///使用 “abstract” 修饰符来定义一个抽象类，该类 不能被实例化。
///抽象类在定义接口的时候非常有用，
abstract class Study{
  void study();

}


class StudyFlutter extends Study{
  @override
  void study() {
    print("StudyFlutter");
  }
}

class Test extends Person with Study{
  Test(String name, int age) : super(name, age);

  @override
  void study() {
    // TODO: implement study
  }

}